package lct.spritecompiler;

import java.awt.image.BufferedImage;
import java.util.Vector;

import lct.imag.*;
import lct.spri.*;
import lct.util.FileUtility;
import lct.util.PathUtility;

public class Program {
	private static XMLConverter s_xmlConverter;
	private static lct.spri.XMLConverter s_spriXMLConverter;	
	private static lct.spri.BinaryConverter s_spriBinaryConverter;
	private static lct.imag.ImageConverter s_textImageConverter;
	private static lct.imag.BinaryConverter s_textBinaryConverter;
	
	private static final String TASK_OPTION = "-task=";
	private static final String TASK_EXAMPLE = "example";
	private static final String TASK_PLOT = "plot";
	private static final String TASK_PACKAGE = "package";
	private static final String TASK_TEST = "test";
	private static final String PLOT_DIRECTORY_PATH_OPTION = "-plotDirectoryPath=";
	private static final String MANIFEST_FILE_PATH_OPTION = "-manifestFilePath=";
	private static final String TEMP_DIRECTORY_PATH_OPTION = "-tempDirectoryPath=";
	private static final String PACKAGE_FILE_PATH_OPTION = "-packageFilePath=";
	
	private static String s_task;
	private static String s_plotDirectoryPath;
	private static String s_manifestFilePath;
	private static String s_tempDirectoryPath;
	private static String s_packageFilePath;
	private static boolean s_bigEndian = false;
	
	private static Manifest s_manifest;
	
	private static void processArguments(String[] args) {
		for (int index = 0; index < args.length; ++index) {
			String arg = args[index];
			if (arg.startsWith(TASK_OPTION)) {
				s_task = arg.substring(TASK_OPTION.length());
			}
			else if (arg.startsWith(PLOT_DIRECTORY_PATH_OPTION)) {
				s_plotDirectoryPath = arg.substring(PLOT_DIRECTORY_PATH_OPTION.length());
			}
			else if (arg.startsWith(MANIFEST_FILE_PATH_OPTION)) {
				s_manifestFilePath = arg.substring(MANIFEST_FILE_PATH_OPTION.length());
			}
			else if (arg.startsWith(TEMP_DIRECTORY_PATH_OPTION)) {
				s_tempDirectoryPath = arg.substring(TEMP_DIRECTORY_PATH_OPTION.length());
			}
			else if (arg.startsWith(PACKAGE_FILE_PATH_OPTION)) {
				s_packageFilePath = arg.substring(PACKAGE_FILE_PATH_OPTION.length());
			}
		}
	}
	
	private static void generateExamples() {
		Figure figure = Examples.createFigure();
		s_spriXMLConverter.storeFigure(figure, "./example_figure.xml");		
		
		Animation animation1 = Examples.createAnimation1();
		s_spriXMLConverter.storeAnimation(animation1, "./example_animation_1.xml");
		
		Animation animation2 = Examples.createAnimation2();
		s_spriXMLConverter.storeAnimation(animation2, "./example_animation_2.xml");
		
		Animation animation3 = Examples.createAnimation3();
		s_spriXMLConverter.storeAnimation(animation3, "./example_animation_3.xml");
		
		Texture textureStripA = Examples.createTextureStripA();
		s_textImageConverter.storeTextureTGA(textureStripA, "./example_texture_strip_A.tga");
		
		Texture textureStripB = Examples.createTextureStripB();
		s_textImageConverter.storeTextureTGA(textureStripB, "./example_texture_strip_B.tga");
		
		Texture textureStripC = Examples.createTextureStripC();
		s_textImageConverter.storeTextureTGA(textureStripC, "./example_texture_strip_C.tga");
		
		//Texture hermiteTestTexture = Examples.createHermiteTestTexture();
		//s_textImageConverter.storeTextureTGA(hermiteTestTexture, "./hermite_test_texture.tga");
		
		Manifest manifest = Examples.createManifest("./");
		s_xmlConverter.storeManifest(manifest, "./example_manifest.xml");
	}
	
	private static void plotAnimations() {
		if ((s_manifestFilePath == null) || (s_plotDirectoryPath == null)) {
			System.err.println("Invalid arguments for plot task.");
			System.exit(-1);
		}
		
		System.out.println("Plotting animations: " + PathUtility.getFileNameNoExtension(s_manifestFilePath));
		s_manifest = s_xmlConverter.loadManifest(s_manifestFilePath);
		if (s_manifest == null) {
			System.err.println("Error loading manifest.");
			System.exit(-1);
		}
		
		FileUtility.createDirectory(s_plotDirectoryPath);
		
		for (Manifest.AnimationEntry animationEntry: s_manifest.animationEntryVector) {
			String xmlFilePath = animationEntry.filePath;			
			
			if (!FileUtility.exists(xmlFilePath)) {
				System.err.println("Referenced animation file does not exist: " + animationEntry.filePath);
				System.exit(-1);
			}
			
			Animation animation = s_spriXMLConverter.loadAnimation(xmlFilePath);
			AnimationUtility.calculateSlopes(animation);
			for (Animation.Track track: animation.trackVector) {
				String tgaFileName = PathUtility.getFileNameNoExtension(animationEntry.filePath) + "_" + track.targetName + "_" + track.targetPropertyType.toString() + ".tga";
				String tgaFilePath = PathUtility.combineFull(s_plotDirectoryPath, tgaFileName);
								
				BufferedImage bufferedImage = AnimationUtility.plotToBufferedImage(track);
				Texture texture = TextureUtility.fromBufferedImage(bufferedImage);
				s_textImageConverter.storeTextureTGA(texture, tgaFilePath);
			}
		}
	}
	
	private static void processPackage() {
		if ((s_manifestFilePath == null) || (s_tempDirectoryPath == null) || (s_packageFilePath == null)) {
			System.err.println("Invalid arguments for package task.");
			System.exit(-1);
		}		
		
		System.out.println("Processing package: " + PathUtility.getFileNameNoExtension(s_manifestFilePath));
		s_manifest = s_xmlConverter.loadManifest(s_manifestFilePath);
		if (s_manifest == null) {
			System.err.println("Error loading manifest.");
			System.exit(-1);
		}
		
		
		
		boolean anyEntryProcessed = false;
		Vector<String> binaryFilePathVector = new Vector<String>();
		
		String figureTempDirectoryPath = PathUtility.combineFull(s_tempDirectoryPath, "figure");
		FileUtility.createDirectory(figureTempDirectoryPath);
		
		for (Manifest.FigureEntry figureEntry: s_manifest.figureEntryVector) {
			String binaryFileName = PathUtility.getFileNameNoExtension(figureEntry.filePath) + ".bin";
			String binaryFilePath = PathUtility.combineFull(figureTempDirectoryPath, binaryFileName);
			binaryFilePathVector.add(binaryFilePath);
			
			anyEntryProcessed |= processFigure(figureEntry.filePath, binaryFilePath);
		}
		
		String animationTempDirectoryPath = PathUtility.combineFull(s_tempDirectoryPath, "animation");
		FileUtility.createDirectory(animationTempDirectoryPath);
		
		for (Manifest.AnimationEntry animationEntry: s_manifest.animationEntryVector) {
			String binaryFileName = PathUtility.getFileNameNoExtension(animationEntry.filePath) + ".bin";
			String binaryFilePath = PathUtility.combineFull(animationTempDirectoryPath, binaryFileName);
			binaryFilePathVector.add(binaryFilePath);
			
			anyEntryProcessed |= processAnimation(animationEntry.filePath, binaryFilePath);
		}
		
		String textureStripTempDirectoryPath = PathUtility.combineFull(s_tempDirectoryPath, "textureStrip");
		FileUtility.createDirectory(textureStripTempDirectoryPath);
		
		for (Manifest.TextureStripEntry textureStripEntry: s_manifest.textureStripEntryVector) {
			String binaryFileName = PathUtility.getFileNameNoExtension(textureStripEntry.filePath) + ".bin";
			String binaryFilePath = PathUtility.combineFull(textureStripTempDirectoryPath, binaryFileName);
			binaryFilePathVector.add(binaryFilePath);
			
			anyEntryProcessed |= processTextureStrip(textureStripEntry.filePath, binaryFilePath);
		}
		
		if (anyEntryProcessed || !FileUtility.exists(s_packageFilePath)) {
			System.out.println("Consolidating package files");
			FileUtility.consolidateFiles(binaryFilePathVector, s_packageFilePath);
		}
		else {
			System.out.println("Package up to date");
		}
	}
	
	private static boolean processFigure(String xmlFilePath, String binaryFilePath) {
		if (!FileUtility.exists(xmlFilePath)) {
			System.err.println("Referenced figure file does not exist: " + xmlFilePath);
			System.exit(-1);
		}
		
		if (FileUtility.isOutdated(binaryFilePath, xmlFilePath)) {
			System.out.println("Converting figure: " + PathUtility.getFileNameNoExtension(xmlFilePath));
			Figure figure = s_spriXMLConverter.loadFigure(xmlFilePath);
			s_spriBinaryConverter.storeFigure(figure, binaryFilePath, s_bigEndian);
			return true;
		}
		else {
			return false;
		}
	}
	
	private static boolean processAnimation(String xmlFilePath, String binaryFilePath) {
		if (!FileUtility.exists(xmlFilePath)) {
			System.err.println("Referenced animation file does not exist: " + xmlFilePath);
			System.exit(-1);
		}
		
		if (FileUtility.isOutdated(binaryFilePath, xmlFilePath)) {
			System.out.println("Converting animation: " + PathUtility.getFileNameNoExtension(xmlFilePath));
			Animation animation = s_spriXMLConverter.loadAnimation(xmlFilePath);			
			AnimationUtility.calculateSlopes(animation);
			s_spriBinaryConverter.storeAnimation(animation, binaryFilePath, s_bigEndian);
			return true;
		}
		else {
			return false;
		}
	}
	
	private static boolean processTextureStrip(String imageFilePath, String binaryFilePath) {
		if (!FileUtility.exists(imageFilePath)) {
			System.err.println("Referenced textureStrip file does not exist: " + imageFilePath);
			System.exit(-1);
		}
		
		if (FileUtility.isOutdated(binaryFilePath, imageFilePath)) {
			System.out.println("Converting strip: " + PathUtility.getFileNameNoExtension(imageFilePath));
			Texture texture = s_textImageConverter.loadTextureTGA(imageFilePath);
			Vector<Texture> textureVector = TextureUtility.splitStrip(texture, texture.height, texture.height);
			TextureTable textureTable = new TextureTable();
			textureTable.name = texture.name;
			textureTable.width = textureVector.elementAt(0).width;
			textureTable.height = textureVector.elementAt(0).height;
			textureTable.texelArrayArray = new Texture.TexelRGBA[textureVector.size()][];
			for (int textureIndex = 0; textureIndex < textureVector.size(); ++textureIndex) {
				textureTable.texelArrayArray[textureIndex] = textureVector.elementAt(textureIndex).texelArray;
			}
			s_textBinaryConverter.storeTextureTable(textureTable, binaryFilePath, s_bigEndian);
			return true;
		}
		else {
			return false;
		}
	}
	
	public static void main(String[] args) {
		s_xmlConverter = new XMLConverter();
		s_spriXMLConverter = new lct.spri.XMLConverter();		
		s_spriBinaryConverter = new lct.spri.BinaryConverter();
		s_textImageConverter = new lct.imag.ImageConverter();
		s_textBinaryConverter = new lct.imag.BinaryConverter();
		
		processArguments(args);
		if (s_task == null) {
			System.err.println("Invalid task specified");
			System.exit(-1);
		}
		
		switch (s_task) {
		case TASK_EXAMPLE:
			generateExamples();
			break;
		case TASK_PLOT:
			plotAnimations();
			break;
		case TASK_PACKAGE:
			processPackage();
			break;
		case TASK_TEST:
			generateExamples();
			plotAnimations();
			processPackage();
			break;
		default:
			System.err.println("Invalid task specified");
			System.exit(-1);
		}
	}
}
